package com.yangjie.common.dao.criteria;

import java.util.LinkedList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

public class CriteriaUtils {
	public static void toHibernateCriteria(Criteria hbnCriteria,
			PaginationQueryCriteria criteria) {
		toHibernateCriteria(hbnCriteria, criteria.getCriteria());
		hbnCriteria.setFirstResult(criteria.getFirstRow());
		hbnCriteria.setMaxResults(criteria.getPageSize());
	}
	
//	public static void toHibernateCountCriteria(Criteria hbnCriteria,
//			PaginationQueryCriteria criteria) {
//		hbnCriteria.setProjection(Projections.rowCount());
//		toHibernateCriteria(hbnCriteria, criteria);
//	}
//	
//	public static void toHibernateCountCriteria(Criteria hbnCriteria,
//			QueryCriteria criteria) {
//		hbnCriteria.setProjection(Projections.rowCount());
//		toHibernateCriteria(hbnCriteria, criteria);
//	}
	
	public static void toHibernateCriteria(Criteria hbnCriteria,
			QueryCriteria criteria) {
		List<CriteriaExpressionIF> exprList = criteria.getCritiriaExpressions();
		String logicOp = criteria.getCriteriaRelation();
		List<Criterion> criterionList = new LinkedList<Criterion>();
		
		for (CriteriaExpressionIF expr : exprList) {
			Criterion criterion = expr.toCriterion();
			if (criterion != null) {
				if (logicOp.equalsIgnoreCase("and")) {
					hbnCriteria.add(criterion);
				} else {
					criterionList.add(criterion);
				}
			}
		}
		if(logicOp.equalsIgnoreCase("or")) {
			Criterion criterion2 = null;
			for(Criterion criterion: criterionList) {
				criterion2 = Restrictions.or(criterion, Restrictions.or(criterion, criterion));
			}
			hbnCriteria.add(criterion2);
		}
		
		for(OrderByExpression orderByExpression: criteria.getOrderByExpressions()) {
			hbnCriteria.addOrder(orderByExpression.toHbnOrder());
		}
	}
	
	public Criterion buildOrRestrictions(List<Criterion> criterionList) {
		int size = criterionList.size();
		switch(size) {
			case 0:return null;
			case 1:return criterionList.get(0);
			case 2:return Restrictions.or(criterionList.get(0), criterionList.get(1));
			default:
				Criterion before = Restrictions.or(criterionList.get(0), criterionList.get(1));
				for(int i = 2; i < criterionList.size(); i++) {
					before = buildOrRestrictions(before, criterionList.get(i));
				}
				return before;
		}
		
			
		
	}
	private Criterion buildOrRestrictions(Criterion before, Criterion newCriterion) {
		return Restrictions.or(newCriterion, before);
	}

}
